home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / stngpasm / pure_c / include / uran / uran_env.sh < prev    next >
Encoding:
Text File  |  1997-08-08  |  16.6 KB  |  582 lines

  1. ;----------------------------------------------------------------------------
  2. ;File name:    URAn_ENV.SH            Revision date:    1997.08.08
  3. ;Creator:    Ulf Ronald Andersson        Creation date:    1994.08.31
  4. ;(c)1994 by:    Ulf Ronald Andersson        All rights reserved
  5. ;Released as:    FREEWARE            (commercial sale forbidden)
  6. ;----------------------------------------------------------------------------
  7. ;Purpose:    Macro library for environmemt handler
  8. ;----------------------------------------------------------------------------
  9. ;Required header declarations:
  10. ;
  11. ;    include    "uran\STRUCT.SH"
  12. ;    include    "uran\URAn_SYS.SH"
  13. ;    include    "uran\URAn_ENV.SH"
  14. ;
  15. ;----------------------------------------------------------------------------
  16. ;Library macros:
  17. ;
  18. ;old_env_base      d0 -> basepage of oldest env from basepage (a0)
  19. ;
  20. ;measure_args      d0 = total size of d0 args (a0) (as needed in env)
  21. ;measure_env      d0 = total size of env (a0)
  22. ;measure_var      d0 = size of current string (a0)
  23. ;next_env_var      d0 -> next var in env (a0) (even NUL) / NULL
  24. ;next_value      d0 -> value of env var (a0) / E_FILNF
  25. ;
  26. ;ultoa_8hex      conv d0 to 8 ascii hex (a0),  d0 = a0+8
  27. ;
  28. ;eval_number      d0 = numeric value of prefixed ($=hex) string (a0)
  29. ;eval_hex_num      d0 = numeric value of hex string (a0)
  30. ;eval_dec_num      d0 = numeric value of decimal string (a0)
  31. ;eval_bin_num      d0 = numeric value of binary string (a0)
  32. ;eval_base_d0      d0 = numeric value of string (a0) in base d0
  33. ;
  34. ;make_env_var  Make new var (a0) in env (a1), d0= a0 / E_ACCDN
  35. ;kill_env_var  Kill old var (a0) in env (a1), d0= a0 / E_FILNF
  36. ;find_env_var  Find old var (a0) in env (a1), d0 -> var / E_FILNF
  37. ;eval_env_var  d0 = numeric value of env var / E_RANGE / E_FILNF
  38. ;
  39. ;NB: 'measure_args' needs d0/a0 as per URAn_APP.S 'arg_cnt/arg_ptr'
  40. ;NB: 'eval_...' routines return E_RANGE in d0 at failed conversion
  41. ;NB: 'next_...' do not flag NUL strings as errors, but you must test for it.
  42. ;----------------------------------------------------------------------------
  43. ;NB: You must include the following line somewhere after the macro calls
  44. ;    "make    ENV_links"
  45. ;NB: That will cause the needed routines to be included at that point.
  46. ;NB: You may do this several times (after further calls), and at each
  47. ;NB: point only the 'newly' referenced routines will be added to the code.
  48. ;NB: A dummy reference macro exists, so routines can be added to code even
  49. ;NB: without calling them.  The macro is '_uniref', used as below:
  50. ;    "_uniref old_env_base"
  51. ;----------------------------------------------------------------------------
  52. ; definitions:
  53. ;----------------------------------------------------------------------------
  54. ;
  55.     _unidec    old_env_base
  56.     _unidec    ultoa_8hex
  57.     _unidec    measure_args
  58.     _unidec    measure_env
  59.     _unidec    measure_var
  60.     _unidec    make_env_var
  61.     _unidec    kill_env_var
  62.     _unidec    find_env_var
  63.     _unidec    eval_env_var
  64.     _unidec    eval_number
  65.     _unidec    next_env_var
  66.     _unidec    next_value
  67.     _unidec    eval_number
  68.     _unidec    eval_base_d0
  69. ;
  70.     .macro    ENV_links
  71.     _unidef    old_env_base
  72.     _unidef    ultoa_8hex
  73.     _unidef    measure_args
  74.     _unidef    measure_env
  75.     _unidef    measure_var
  76.     _unidef    make_env_var
  77.     _unidef    kill_env_var
  78.     _unidef    find_env_var
  79.     _unidef    eval_env_var
  80.     _unidef    eval_number
  81.     _unidef    next_env_var
  82.     _unidef    next_value
  83.     _unidef    eval_number
  84.     _unidef    eval_base_d0
  85.     .endm    ;ENV_links
  86. ;
  87. ;----------------------------------------------------------------------------
  88. ;Macro:    old_env_base
  89. ;Entry:    a0 -> basepage
  90. ;Exit:    d0 -> basepage of oldest valid environment
  91. ;
  92.     .macro    old_env_base
  93.     _uniref    old_env_base
  94.     bsr    code_old_env_base
  95.     .endm    ;old_env_base
  96. ;
  97. ;
  98.     .macro    code_old_env_base
  99.     movem.l    d1/a0/a1,-(sp)
  100. .loop:
  101.     move.l    a0,d0            ;d0 = current basepage ptr
  102.     move.l    bp_parent_p(a0),d1
  103.     ble.s    .exit_loop        ;exit if no parent
  104.     move.l    d1,a0            ;a0 = next older basepage ptr
  105.     cmp.l    bp_parent_p(a0),d0
  106.     beq.s    .exit_loop        ;exit at self_parent
  107.     move.l    bp_environ_p(a0),d1
  108.     ble.s    .exit_loop        ;exit at invalid environ_p
  109.     move.l    d1,a1            ;a1 = next older environment ptr
  110.     tst.b    (a1)
  111.     bne.s    .loop            ;loop until empty environment found
  112.     tst.b    1(a1)
  113.     bne.s    .loop            ;loop until empty environment found
  114. .exit_loop:
  115.     movem.l    (sp)+,d1/a0/a1
  116.     rts
  117.     .endm    ;code_old_env_base
  118. ;
  119. ;----------------------------------------------------------------------------
  120. ;Macro:    ultoa_8hex
  121. ;Entry:    d0 =    unsigned long for conversion
  122. ;  "    a0 ->    8 byte ascii buffer
  123. ;Exit:    No regs altered
  124. ;
  125.     .macro    ultoa_8hex
  126.     _uniref    ultoa_8hex
  127.     bsr    code_ultoa_8hex
  128.     .endm    ;ultoa_8hex
  129. ;
  130. ;
  131.     .macro    code_ultoa_8hex
  132.     movem.l    d1-d2/a0,-(sp)    ;push registers
  133.     moveq    #8-1,d2        ;prep d2 for 8 digits
  134. .loop:                ;loop: to convert 8 digits to ascii
  135.     rol.l    #4,d0        ;  shift d0 top digit to low byte
  136.     move.b    d0,d1        ;  copy d0 low byte to d1
  137.     and    #$0F,d1        ;  isolate low digit in d1
  138.     add    #'0',d1        ;  convert to ascii based on '0'
  139.     cmp    #'9',d1        ;  digit ok ?
  140.     bls.s    .got_digit    ;  go store that ascii if '0'..'9'
  141.     add    #'A'-'9'-1,d1    ;  reconvert to ascii based at 'A'-10
  142. .got_digit:
  143.     move.b    d1,(a0)+    ;  store new ascii digit
  144.     dbra    d2,.loop    ;loop] for 8 digits
  145.     move.l    a0,d0        ;return d0 -> beyond new string
  146.     movem.l    (sp)+,d1-d2/a0    ;pull registers
  147.     rts
  148.     .endm    ;code_ultoa_8hex
  149. ;
  150. ;----------------------------------------------------------------------------
  151. ;Macro:    measure_args
  152. ;Entry:    a0 -> argument string
  153. ;  "    d0 =  argument count  (+1 for progname)
  154. ;Exit:    d0 =  total sum of string lengths
  155. ;
  156.     .macro    measure_args
  157.     _uniref    measure_args
  158.     _uniref    next_env_var
  159.     bsr    code_measure_args
  160.     .endm    ;measure_args
  161. ;
  162. ;
  163.     .macro    code_measure_args
  164.     movem.l    d1/a0,-(sp)
  165.     tst.l    4(sp)
  166.     beq.s    .exit        ;NULL ptr => zero size
  167.     move.l    d0,d1
  168.     subq    #1,d1
  169.     ble.s    .exit        ;zero real args => zero size
  170.     next_env_var        ;pass program name arg
  171.     move.l    d0,a0
  172.     subq    #1,d1
  173. .loop_1:
  174.     tst.b    (a0)
  175.     beq.s    .exit        ;exit at NUL arg
  176. .loop_2:
  177.     tst.b    (a0)+
  178.     bne.s    .loop_2
  179.     dbra    d1,.loop_1
  180. .exit:
  181.     sub.l    4(sp),a0
  182.     move.l    a0,d0
  183.     movem.l    (sp)+,d1/a0
  184.     rts            ;return d0 = total size of argument strings
  185.     .endm    ;code_measure_args
  186. ;
  187. ;----------------------------------------------------------------------------
  188. ;Macro:    measure_env
  189. ;Entry:    a0 -> environment
  190. ;Exit:    d0 =  total size of environment
  191. ;
  192.     .macro    measure_env
  193.     _uniref    measure_env
  194.     bsr    code_measure_env
  195.     .endm    ;measure_env
  196. ;
  197. ;
  198.     .macro    code_measure_env
  199.     move.l    a0,-(sp)
  200.     move.l    a0,d0
  201.     beq.s    .exit    ;NULL ptr => zero size
  202. .loop:
  203.     tst.b    (a0)+
  204.     bne.s    .loop
  205.     tst.b    (a0)+
  206.     bne.s    .loop
  207. .exit:
  208.     sub.l    (sp),a0
  209.     move.l    a0,d0
  210.     movea.l    (sp)+,a0
  211.     rts        ;return d0 = environment size (incl termination)
  212.     .endm    ;code_measure_env
  213. ;
  214. ;----------------------------------------------------------------------------
  215. ;Macro:    measure_var
  216. ;Entry:    a0 -> string
  217. ;Exit:    d0 =  total size of string (incl NUL), unless NULL
  218. ;
  219.     .macro    measure_var
  220.     _uniref    measure_var
  221.     bsr    code_measure_var
  222.     .endm    ;measure_var
  223. ;
  224. ;
  225.     .macro    code_measure_var
  226.     move.l    a0,-(sp)
  227.     move.l    a0,d0
  228.     beq.s    .exit    ;NULL ptr => zero size
  229. .loop:
  230.     tst.b    (a0)+
  231.     bne.s    .loop
  232. .exit:
  233.     sub.l    (sp),a0
  234.     move.l    a0,d0
  235.     movea.l    (sp)+,a0
  236.     rts        ;return d0 = environment size (incl termination)
  237.     .endm    ;code_measure_var
  238. ;
  239. ;----------------------------------------------------------------------------
  240. ;Macro:    eval_env_var
  241. ;Entry:    a0 -> var_name
  242. ;  "    a1 -> environment
  243. ;Exit:    d0 =  converted ULONG, unless E_RANGE
  244. ;
  245.     .macro    eval_env_var
  246.     _uniref    eval_env_var
  247.     _uniref    eval_number
  248.     bsr    code_eval_env_var
  249.     .endm
  250. ;
  251. ;
  252.     .macro    code_eval_env_var
  253.     movem.l    a0/a1,-(sp)
  254.     find_env_var
  255.     tst.l    d0
  256.     ble.s    .exit
  257.     move.l    d0,a0
  258.     eval_number
  259. .exit:
  260.     movem.l    (sp)+,a0/a1
  261.     rts
  262.     .endm    ;code_eval_env_var
  263. ;
  264. ;----------------------------------------------------------------------------
  265. ;Macro:    kill_env_var
  266. ;Entry:    a0 -> var_name
  267. ;  "    a1 -> environment
  268. ;Exit:    d0 -> altered environment, unless E_FILNF  (var not found)
  269. ;
  270.     .macro    kill_env_var
  271.     _uniref    kill_env_var
  272.     bsr    code_kill_env_var
  273.     .endm    ;kill_env_var
  274. ;
  275. ;
  276.     .macro    code_kill_env_var
  277.     find_env_var
  278.     tst.l    d0
  279.     ble.s    .exit        ;exit with d0 = error code if not found
  280.     movem.l    a0-a1,-(sp)    ;push registers
  281.     move.l    d0,a0        ;a0 -> found var, == move destination
  282.     next_env_var
  283.     move.l    d0,a1        ;a1 -> next var, == move source
  284. .loop_1:            ;loop: move all remaining strings in env
  285.     move.b    (a1)+,(a0)+    ;  move 1'st byte of a string
  286.     beq.s    .env_end    ;exit loop at end of environment
  287. .loop_2:            ;  loop: move rest of string
  288.     move.b    (a1)+,(a0)+    ;    move a byte of string
  289.     bne.s    .loop_2        ;  loop] until string terminates
  290.     bra.s    .loop_1        ;loop] for entire environment
  291. ;
  292. .env_end:
  293.     clr.b    (a0)+        ;ensure environment termination
  294.     movem.l    (sp)+,a0-a1    ;pull registers
  295.     move.l    a1,d0        ;return d0 -> altered env
  296. .exit:
  297.     rts
  298.     .endm    ;code_kill_env
  299. ;
  300. ;----------------------------------------------------------------------------
  301. ;Macro:    make_env_var
  302. ;Entry:    a0 -> var_name
  303. ;  "    a1 -> environment
  304. ;Exit:    d0 -> altered environment, unless E_ACCDN  (var already exists
  305. ;
  306. ;NB: 'make_env_var' does not check sizes,
  307. ;    so caller must be sure env (a1) has enough room.
  308. ;
  309.     .macro    make_env_var
  310.     _uniref    make_env_var
  311.     _uniref    measure_env
  312.     bsr    code_make_env_var
  313.     .endm    ;make_env_var
  314. ;
  315. ;
  316.     .macro    code_make_env_var
  317.     find_env_var
  318.     move.l    d0,-(sp)
  319.     moveq    #E_ACCDN,d0    ;prep error flag 'access denied'
  320.     tst.l    (sp)+
  321.     bgt.s    .exit        ;exit with d0 = error code if found
  322.     tst.b    (a0)
  323.     beq.s    .exit        ;exit with d0 = error code for NUL var
  324.     movem.l    a0-a1,-(sp)    ;push registers
  325.     move.l    a1,a0        ;a0 -> env
  326.     measure_env        ;d0 = total size of env
  327.     add.l    d0,a1        ;a1 -> beyond env
  328.     subq.l    #1,a1        ;a1 -> termination NUL of env
  329.     cmp.l    #2,d0        ;empty environment ?
  330.     bne.s    .get_str    ;if not, go keep a1 as move destination
  331.     subq.l    #1,a1        ;a1 -> NUL string in empty environment
  332. .get_str:
  333.     move.l    (sp),a0        ;a0 -> new string for env
  334. .loop:                ;loop: copy entire new string
  335.     move.b    (a0)+,(a1)+    ;  copy a byte of new string
  336.     bne.s    .loop        ;loop] until string terminated
  337.     clr.b    (a1)+        ;terminate env
  338.     movem.l    (sp)+,a0-a1    ;pull registers
  339.     move.l    a1,d0        ;return d0 -> altered env
  340. .exit:
  341.     rts
  342.     .endm    ;code_make_env_var
  343. ;
  344. ;----------------------------------------------------------------------------
  345. ;Macro:    find_env_var
  346. ;Entry:    a0 -> var_name
  347. ;  "    a1 -> environment
  348. ;Exit:    d0 -> found var name, unless E_FILNF  (var not found)
  349. ;
  350.     .macro    find_env_var
  351.     _uniref    find_env_var
  352.     bsr    code_find_env_var
  353.     .endm    ;find_env_var
  354. ;
  355. ;
  356.     .macro    code_find_env_var
  357.     movem.l    d1/a0-a3,-(sp)    ;push registers
  358.     move.l    a1,d0
  359.     beq.s    .env_end    ;NULL env ptr => error
  360.     move.l    a0,d0
  361.     beq.s    .env_end    ;NULL var ptr => error
  362.     move.l    a0,a2        ;a2 -> var to find
  363. .next_var_loop:            ;loop: check vars in env
  364.     move.l    a1,a3        ;  a3 -> possible found var (untested)
  365.     move.l    a2,a0
  366.     tst.b    (a1)        ;  environment end ?
  367.     beq.s    .env_end
  368. .var_loop:            ;  loop: check a var in env
  369.     move.b    (a1)+,d0    ;    termination of var in env ?
  370.     beq.s    .next_var_loop    ;loop] at premature (erroneous) end of var
  371.     cmp.b    (a0)+,d0    ;    sought var char identical to env ?
  372.     bne.s    .skip_rest_loop    ;    exit loop to skip rest if different
  373.     cmp.b    #'=',d0        ;    end of var ?
  374.     bne.s    .var_loop    ;  loop] check entire name
  375.     move.l    a3,d0        ;return d0 -> found string
  376.     bra.s    .exit        ;go exit sub
  377. ;
  378. .skip_rest_loop:        ;  loop: ignore value in env
  379.     tst.b    (a1)+        ;    string termination ?
  380.     bne.s    .skip_rest_loop    ;  loop] skip entire string
  381.     bra.s    .next_var_loop    ;loop] test more vars
  382. ;
  383. .env_end:
  384.     moveq    #E_FILNF,d0    ;return d0 = E_FILNF, var not found
  385. .exit:
  386.     movem.l    (sp)+,d1/a0-a3    ;pull registers
  387.     rts
  388.     .endm    ;code_find_env_var
  389. ;
  390. ;----------------------------------------------------------------------------
  391. ;Macro:    next_env_var
  392. ;Entry:    a0 -> any pos in environment
  393. ;Exit:    d0 -> next string (may be NUL), unless NULL
  394. ;
  395.     .macro    next_env_var
  396.     _uniref    next_env_var
  397.     bsr    code_next_env_var
  398.     .endm    ;next_env_var
  399. ;
  400. ;
  401.     .macro    code_next_env_var
  402.     move.l    a0,-(sp)    ;push a0
  403.     move.l    a0,d0
  404.     beq.s    .exit        ;NULL ptr => exit (returning NULL)
  405. .loop:                ;loop: pass a string in env
  406.     tst.b    (a0)+        ;termination of string ?
  407.     bne.s    .loop        ;loop] pass entire string
  408.     move.l    a0,d0        ;return d0 -> found var
  409. .exit:
  410.     move.l    (sp)+,a0    ;pull a0
  411.     rts
  412.     .endm    ;code_next_env_var
  413. ;
  414. ;----------------------------------------------------------------------------
  415. ;Macro:    next_value
  416. ;Entry:    a0 -> any pos in environment
  417. ;Exit:    d0 -> next value string (may be NUL), unless E_FILNF
  418. ;
  419.     .macro    next_value
  420.     _uniref    next_value
  421.     bsr    code_next_value
  422.     .endm    ;next_value
  423. ;
  424. ;
  425.     .macro    code_next_value
  426.     move.l    a0,-(sp)    ;push a0
  427.     move.l    a0,d0
  428.     beq.s    .error        ;NULL ptr => error
  429. .loop:                ;loop: pass var to value point
  430.     move.b    (a0)+,d0    ;  termination of string in env ?
  431.     beq.s    .error        ;go exit if no value found
  432.     cmp.b    #'=',d0        ;  end of var name ?
  433.     bne.s    .loop        ;loop] pass entire name of var
  434.     move.l    a0,d0        ;return d0 -> found value
  435.     bra.s    .exit
  436. ;
  437. .error:
  438.     moveq    #E_FILNF,d0    ;return d0 = E_FILNF, value not found
  439. .exit:
  440.     move.l    (sp)+,a0    ;pull a0
  441.     rts
  442.     .endm    ;code_next_value
  443. ;
  444. ;----------------------------------------------------------------------------
  445. ;Macro:    eval_number
  446. ;Entry:    a0 -> ascii of number to evaluate
  447. ;Exit:    d0 =  converted ULONG, unless E_RANGE
  448. ;
  449.     .macro    eval_number
  450.     _uniref    eval_number
  451.     bsr    code_eval_number
  452.     .endm    ;eval_number
  453. ;
  454. ;
  455.     .macro    code_eval_number
  456.     move.l    a0,-(sp)    ;push a0
  457.     move.l    a0,d0
  458.     beq.s    .bad_value    ;NULL ptr => error
  459.     moveq    #10,d0        ;assume decimal base
  460.     cmp.b    #'0',(a0)    ;first char possibly digit ?
  461.     bhs.s    .eval_number    ;if so, go evaluate number
  462.     moveq    #16,d0        ;assume hexadecimal base
  463.     cmp.b    #'$',(a0)+    ;'$' present as hex prefix ?
  464.     bhs.s    .eval_number    ;if so, go evaluate number
  465.     moveq    #2,d0        ;assume binary base
  466.     cmp.b    #'%',-1(a0)    ;'%' present as binary prefix ?
  467.     bhs.s    .eval_number    ;if so, go evaluate number
  468. .bad_value:
  469.     moveq    #E_RANGE,d0    ;return E_RANGE for illegal value
  470.     bra.s    .exit
  471. ;
  472. .eval_number:
  473.     eval_base_d0
  474. .exit:
  475.     movea.l    (sp)+,a0    ;pull a0
  476.     rts
  477.     .endm    ;code_eval_number
  478. ;
  479. ;----------------------------------------------------------------------------
  480. ;Macro:    eval_hex_num
  481. ;Entry:    a0 -> ascii of hex number to evaluate
  482. ;Exit:    d0 =  converted ULONG, unless E_RANGE
  483. ;
  484.     .macro    eval_hex_num
  485.     _uniref    eval_base_d0
  486.     bsr    code_eval_hex_num
  487.     .endm    ;eval_hex_num
  488. ;
  489. ;----------------------------------------------------------------------------
  490. ;Macro:    eval_dec_num
  491. ;Entry:    a0 -> ascii of decimal number to evaluate
  492. ;Exit:    d0 =  converted ULONG, unless E_RANGE
  493. ;
  494.     .macro    eval_dec_num
  495.     _uniref    eval_base_d0
  496.     bsr    code_eval_dec_num
  497.     .endm    ;eval_dec_num
  498. ;
  499. ;----------------------------------------------------------------------------
  500. ;Macro:    eval_bin_num
  501. ;Entry:    a0 -> ascii of binary number to evaluate
  502. ;Exit:    d0 =  converted ULONG, unless E_RANGE
  503. ;
  504.     .macro    eval_bin_num
  505.     _uniref    eval_base_d0
  506.     bsr    code_eval_bin_num
  507.     .endm    ;eval_bin_num
  508. ;
  509. ;----------------------------------------------------------------------------
  510. ;Macro:    eval_base_d0
  511. ;Entry:    a0 -> ascii of binary number to evaluate
  512. ;  "    d0 =  number base for conversion
  513. ;Exit:    d0 =  converted ULONG, unless E_RANGE
  514. ;
  515.     .macro    eval_base_d0
  516.     _uniref    eval_base_d0
  517.     bsr    eval_base_d0_ia0
  518.     .endm    ;eval_base_d0
  519. ;
  520.     .macro    code_eval_base_d0
  521.     bra.s    eval_base_d0_ia0
  522. ;
  523. code_eval_bin_num:            ;evaluate binary string at (a0)
  524.     moveq    #2,d0
  525.     bra.s    eval_base_d0_ia0
  526. ;
  527. code_eval_dec_num:            ;evaluate decimal string at (a0)
  528.     moveq    #10,d0
  529.     bra.s    eval_base_d0_ia0
  530. ;
  531. code_eval_hex_num:            ;evaluate hexadecimal string at (a0)
  532.     moveq    #16,d0
  533. eval_base_d0_ia0:        ;evaluate string at (a0) in base d0
  534.     movem.l    d1-d3/a0,-(sp)    ;push registers
  535.     move    d0,d3        ;d3 = number base
  536.     move.l    a0,d0
  537.     beq.s    .bad_value    ;NULL ptr => error
  538.     tst.b    (a0)
  539.     beq.s    .bad_value    ;return error if no digits present
  540.     clr.l    d1        ;pre_clear total value
  541.     clr.l    d0        ;pre_clear digit value
  542. .get_value_loop:
  543.     move.b    (a0)+,d0
  544.     beq.s    .got_value    ;return value at end of string
  545.     sub.b    #'0',d0
  546.     blo.s    .bad_value    ;return error for digit too low
  547.     cmp.b    #9,d0
  548.     bls.s    .test_base    ;go test digits 0..9 as-is
  549.     add.b    #'0'+$A-'A',d0    ;adjust for letters as digits
  550.     cmp.b    #10,d0
  551.     blo.s    .bad_value    ;return error for illegal characters
  552. .test_base:
  553.     cmp.b    d3,d0
  554.     bhs.s    .bad_value    ;return error for digit too high    
  555. .good_digit:
  556.     move.l    d1,d2
  557.     swap    d2
  558.     mulu    d3,d2
  559.     swap    d2
  560.     tst    d2
  561.     bne.s    .bad_value    ;return error for value overflow
  562.     clr    d2
  563.     mulu    d3,d1
  564.     add.l    d2,d1
  565.     bcs.s    .bad_value    ;return error for unsigned overflow
  566.     add.l    d0,d1
  567.     bcc.s    .get_value_loop    ;loop for more digits if no overflow
  568. .bad_value:
  569.     moveq    #E_RANGE,d0    ;return E_RANGE for illegal value
  570.     bra.s    .exit
  571. ;
  572. .got_value:
  573.     move.l    d1,d0        ;return value of decimal number
  574. .exit:
  575.     movem.l    (sp)+,d1-d3/a0    ;pull registers
  576.     rts
  577.     .endm    ;code_eval_base_d0
  578. ;
  579. ;----------------------------------------------------------------------------
  580. ;End of file:    URAn_ENV.SH
  581. ;----------------------------------------------------------------------------
  582.